package minidb.record;

import minidb.type.fieldinfo;
import minidb.buffer.Buffer;
import minidb.type.*;
import minidb.type.Const.TYPE;

public class Record {
	private RID rid;
	private int size;
	private java.util.List<fieldinfo> fieldInfo;
	private java.nio.ByteBuffer record;
	public Record(RID rid, int size, java.util.List<fieldinfo> fieldInfo, Buffer buf){
		this.rid = rid;
		this.size = size;
		this.fieldInfo = fieldInfo;
		this.record = java.nio.ByteBuffer.allocateDirect(size);	
		buf.getByte(rid.rid()+1, record, size);
	}
	
	public Record(int size, java.util.ArrayList<fieldinfo> fieldinfo){
		this.size = size;
		this.fieldInfo = fieldinfo;
		record = java.nio.ByteBuffer.allocateDirect(size);
	}
	
	public RID rid(){ return this.rid; }
	
	public int size(){ return this.size; }
	
	public java.nio.ByteBuffer record(){ return this.record; }
	
	public void record(java.nio.ByteBuffer r){
		this.record = r;
	}
	
	public java.util.List<fieldinfo> fieldInfo(){ return this.fieldInfo; }
	
	public void rid(RID rid){ this.rid = rid; }
	
	public void size(int size){ this.size = size; }
	
	public void fieldinfo(java.util.List<fieldinfo> fieldInfo){ this.fieldInfo = fieldInfo; }
	
	public int pos(String name){
		for(int i = 0; i < fieldInfo.size(); i++){
			if(((fieldinfo)fieldInfo.get(i)).name().compareTo(name)==0)
				return i;
		}
		return -1;
	}
	
	public int getInt(int pos){
		return record.getInt(fieldInfo.get(pos-1).position());
	}
	
	public String getString(int pos){
		record.position(fieldInfo.get(pos-1).position());
		int length = (int)record.get();
		byte []bt = new byte[length];
		record.get(bt);
		return new String(bt);		
	}
	
	public Double getDouble(int pos){
		return record.getDouble(fieldInfo.get(pos-1).position());
	}

	public Constant get(int pos){
		fieldinfo info =  this.fieldInfo.get(pos-1);
		if(info.type()==TYPE.INT)
			return new IntConstant(getInt(pos));
		else if(info.type() == TYPE.STRING || info.type()==TYPE.CHAR)
			return new StringConstant(getString(pos));
		else if(info.type() == TYPE.DOUBLE)
			return new DoubleConstant(getDouble(pos));
		else
			return null;
	}
	
	public Constant get(String name){
		int p = pos(name);
		if(p < 0)
			throw new RuntimeException("No such fieldInfo: " + name);
		return get(p+1);
	}
	
	public void put(String name, Constant val){
		int p = pos(name);
		if(p < 0)
			throw new RuntimeException("No such fieldInfo: " + name);
		put(p+1, val);
			
	}
	
	public void put(int pos, Constant val){
		if(IntConstant.class.isInstance(val))
			putInt(pos, (Integer)val.toVal());
		else if(StringConstant.class.isInstance(val))
			putString(pos, (String)val.toVal());
		else if(DoubleConstant.class.isInstance(val))
			putDouble(pos, (Double)val.toVal());
		else
			;
	}
	
	public void putInt(int pos,int val){
		record.putInt(fieldInfo.get(pos-1).position(),val);
	}
	
	public void putDouble(int pos, Double val){
		record.putDouble(fieldInfo.get(pos-1).position(), val);
	}
	
	public void putString(int pos, String val){
		fieldinfo f = fieldInfo.get(pos-1);
		if(f.length()<val.length())
			throw new RuntimeException("STRING VALUE IS TOO LONG: "+  val);
		int position = f.position();
		String s = val;
		int length = f.length();
		if(f.type()==TYPE.CHAR){
			for(int i = s.length(); i!=0 && i < length; i++)
				s+=".";
		}
		record.position(position);
		record.put((byte)s.length());
		record.put(s.getBytes());
	}
}
